/*
Copyright (C) 2003  Pierrick Brihaye
pierrick.brihaye@wanadoo.fr

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
or connect to:
http://www.fsf.org/copyleft/gpl.html
*/

package gpl.pierrick.brihaye.aramorph.lucene;

import gpl.pierrick.brihaye.aramorph.AraMorph;
import gpl.pierrick.brihaye.aramorph.Solution;

import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.logging.Logger;

import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TermAttribute;

/** A filter that will return english glosses from arabic stems.*/
public class ArabicGlosser extends TokenFilter {
	private static final Logger logger = Logger.getLogger(ArabicGlosser.class.getName());
	private AraMorph araMorph = null;
	private boolean processingToken = false;
	private LinkedList<String> tokenGlosses = null;
	private LinkedList<String> tokenPOS = null;
	
	private TermAttribute termAtt;
	private PositionIncrementAttribute posIncrAtt;
	private GlossAttribute glossAtt;
	private POSAttribute posAtt;

	/** Constructs a filter that will return English glosses from Arabic stems.
	 * @param input The token stream from a tokenizer
	 */
	public ArabicGlosser(TokenStream input) {
		this(input, AraMorph.getNormalizedJDBC());
	}
	
	public ArabicGlosser(TokenStream input, AraMorph araMorph) {
		super(input);
		this.araMorph = araMorph;
		termAtt = (TermAttribute) addAttribute(TermAttribute.class);
		posIncrAtt = (PositionIncrementAttribute) addAttribute(PositionIncrementAttribute.class);
		glossAtt = (GlossAttribute) addAttribute(GlossAttribute.class);
		posAtt = (POSAttribute) addAttribute(POSAttribute.class);
	}
	
	/** Returns the Arabic morphological analyzer in use.
	 * @return The Arabic morphological analyzer
	 * @see gpl.pierrick.brihaye.aramorph.AraMorph
	 */
	public AraMorph getAramorph() { return araMorph; }
	
	/** Returns the next gloss for the given stem.
	 * @param firstOne Whether or not this gloss is the first one
	 * @return The gloss. Its <CODE>termText</CODE> is the gloss of the <STRONG>stem</STRONG>. Its <CODE>type</CODE> is the grammatical category of the <STRONG>stem</STRONG>.
	 * When several glosses are available, every emitted token's
	 * <CODE>PositionIncrement</CODE> but the first one is set to <CODE>0</CODE>
	 * @see org.apache.lucene.analysis.Token#setPositionIncrement(int)
	 */
	private void nextGloss(boolean firstOne) {
		posAtt.setPOS(tokenPOS.removeFirst());
		glossAtt.setGloss(tokenGlosses.removeFirst());
		posIncrAtt.setPositionIncrement(firstOne ? 1 : 0);
		//Will there be further treatment for this token ?
		processingToken = !tokenGlosses.isEmpty();

		logger.info("emitted token:"+termAtt.term()+", gloss:"+glossAtt.getGloss()+", POS:"+posAtt.getPOS());
	}
	
	@Override
	public boolean incrementToken() throws IOException {
		if (!processingToken) {
			if (!input.incrementToken())
				return false; // EOS
			//Analyse it (in arabic)
			Iterator<Solution> wordSolutions = araMorph.getWordSolutions(termAtt.term());
			if (wordSolutions != null) {
				tokenGlosses = new LinkedList<String>();
				tokenPOS = new LinkedList<String>();
				while (wordSolutions.hasNext()) {
					Solution currentSolution = wordSolutions.next();
					tokenGlosses.add(currentSolution.getStemGloss());
					tokenPOS.add(currentSolution.getStemPOS(false, false));
				}
				nextGloss(true);
				return true;
			}
			processingToken = false;
			glossAtt.setGloss("no result");
			posAtt.setPOS("no result");
			return true;
		}
		nextGloss(false);
		return true;
	}

	public static void main(String[] args) {
		try {
			String arabicText = "إنما الأعمال بالنيات";
			ArabicTokenizer at = new ArabicTokenizer(new StringReader(arabicText));
			ArabicGlosser ag = new ArabicGlosser(at);
			while (ag.incrementToken()) {
				System.out.println(((TermAttribute)ag.getAttribute(TermAttribute.class)).term()+":"+((GlossAttribute)ag.getAttribute(GlossAttribute.class)).getGloss());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
